/*
  Copyright 2011 Frogtek BOP LLC

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package org.frogtek.database.android;


import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;

import org.frogtek.database.interfaces.IDatabaseConnection;
import org.frogtek.database.interfaces.IDbAdapter;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import org.frogtek.database.interfaces.Database;

public class AndroidDatabaseConnection extends SQLiteOpenHelper implements IDatabaseConnection {
	private static final String TAG = "Android Database Connection";
	private String LOCAL_BD_PATH = "";
	private  List<IDbAdapter> dbAdapterList;
	private  String APP_PACKAGE_NAME = "";
	private Database mDatabase = null;

	public AndroidDatabaseConnection(Context context, Database theDatabase) {
		super(context, theDatabase.getDatabaseName(), null, theDatabase.getDatabaseVersion());

		this.mDatabase = theDatabase;
		LOCAL_BD_PATH = this.mDatabase.getLocalPath();
		APP_PACKAGE_NAME = context.getPackageName();
		dbAdapterList = this.mDatabase.getAdapters();

		try {
			this.createDataBase();
		} catch (IOException e) {
			Log.e("Opening Database", "Problem when opening database");
		}
	}

	private boolean existDatabase() {
		SQLiteDatabase checkDB = null;
		try {
			String myPath = LOCAL_BD_PATH + this.mDatabase.getDatabaseName();
			checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
		} catch (SQLiteException e) {
			Log.e("Android Database", "DataBase doesn't exist... yet");
		}
		if (checkDB != null) {
			checkDB.close();
		}

		return checkDB != null ? true : false;
	}

	private void createDataBase() throws IOException {
		if (!existDatabase()) {
			this.getReadableDatabase();
		}
	}

	private static String getNow() {
		Calendar c = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return sdf.format(c.getTime());
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		/** Create the tables of the database */
		for (int i = 0; i < dbAdapterList.size(); i++) {
			if (dbAdapterList.get(i).getGenerateTableString(null) != null) {
				System.out.println("SQL!! "+dbAdapterList.get(i).getGenerateTableString(APP_PACKAGE_NAME));
				db.execSQL(dbAdapterList.get(i).getGenerateTableString(APP_PACKAGE_NAME));
			}
		}
		for (int i = 0; i < dbAdapterList.size(); i++) {
			dbAdapterList.get(i).executeInitialDataProcess(db, getNow(), APP_PACKAGE_NAME);
		}

		db.setVersion(this.mDatabase.getDatabaseVersion());
	}

	public void execSQL(String sql) {
		this.getWritableDatabase().execSQL(sql);
	}
	public Cursor execRawSQL(String sql) {
		return this.getWritableDatabase().rawQuery(sql, null);
	}
	
	public Cursor execRawSQL(String sql,String[] args) {
		return this.getWritableDatabase().rawQuery(sql, args);
	}
	
	public long insertRow(String databaseTable, ContentValues values) {
		return this.getWritableDatabase().insert(databaseTable, null, values);
	}
	public boolean deleteRow(String tableName, String fieldID, long rowID) {
		return this.getWritableDatabase().delete(tableName, fieldID + " = " + rowID, null) > 0;
	}
	public boolean updateRow(String tableName, ContentValues args, String fieldID, String rowID) {
		return this.getWritableDatabase().update(tableName, args, fieldID + " = " + rowID, null) > 0;
	}
	
    /**
     * Updates a specific row from a table providing the updated information.
     * @param tableName the name of the table
     * @param args the updated fields
     * @param whereClause the where clause
     * @param whereArgs the where arguments
     * @return true if updated, false if not
     * @throws SQLiteException if the update causes an error
     */
    public boolean updateRow(String tableName, ContentValues args, String whereClause, String[] whereArgs) throws SQLiteException {
    	return this.getWritableDatabase().update(tableName, args, whereClause, whereArgs) > 0;
    }

	public boolean deleteAll(String tableName) {
		return this.getWritableDatabase().delete(tableName, null, null) > 0;
	}
	
    /**
     * Fetches the desired data from the specified table
     * @param tableName name of the table to query
     * @param tableFields required data fields
     * @return a cursor with all the requested data
     * @throws SQLiteException if the query causes an error
     */
    public Cursor fetchData(String tableName, String[] tableFields) {
        return this.getReadableDatabase().query(tableName, tableFields, null, null, null, null, null, null);
    }

	public Cursor fetchDataByID(String tableName, String[] tableFields, String rowID) {
		return this.getReadableDatabase().query(tableName, tableFields, "_id = " + rowID, null, null, null, null, null);
	}
	
	 public Cursor fecthSpecificData(String tableName, String[] columns, String fieldToCompare, String fieldValue) {
	        return this.getReadableDatabase().query(tableName, columns, fieldToCompare + " LIKE '%" + fieldValue + "%'", null, null, null, null);
	 }

	@Override
	public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
		for (int i = 0; i < dbAdapterList.size(); i++) {
			dbAdapterList.get(i).executeUpdateProcess(arg1, arg0, getNow(), APP_PACKAGE_NAME);
		}
		Log.w(TAG, "Upgrading database from version " + arg1 + " to "
				+ arg2 + ", which will destroy all old data");
		arg0.setVersion(arg2);
	}

	public void beginTransaction() {
		this.getWritableDatabase().beginTransaction();
	}
	
	/**
     * Commits and ends the current transaction.
     */
    public void commitTransaction() {
    	SQLiteDatabase myDatabase = this.getWritableDatabase();
        try {
        	myDatabase.setTransactionSuccessful();
        } finally {
        	myDatabase.endTransaction();
        }
    }
	
	public void endTransaction() {
		this.getWritableDatabase().endTransaction();
	}

	public Database getDatabase() {
		return mDatabase;
	}
}
